﻿
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace August.UI
{
    public partial class OperationPanel :UserControl
    {
        public Image ContempImage;
        public ShowContainer ShapeContainer = new ShowContainer();
        public event Action<Image> ImageLoaded;
        int shapeContainerWidth = 0;
        int shapeContainerHeight = 0;
        float scalex = 1f;
        float scaley = 1f;
        public event EventHandler<ShapeBase> ShapeSelected;

        Color currentColor = new Color();
        int currentWidth = 1;
        public OperationPanel()
        {
            InitializeComponent();
            Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
           | System.Windows.Forms.AnchorStyles.Left)
           | System.Windows.Forms.AnchorStyles.Right)));

            this.Controls.Add(ShapeContainer);
            ShapeContainer.Dock = DockStyle.Fill;
            this.MouseWheel += OperationPanel_MouseWheel;
            currentColor = Color.Blue;
            ShapeContainer.SizeChanged += ShapeContainer_SizeChanged;
        }

        private void ShapeContainer_SizeChanged(object sender, EventArgs e)
        {
            if (ShapeContainer.Width == 0) return;
            if (ShapeContainer.Height == 0) return;

            shapeContainerWidth = ShapeContainer.Width;
            shapeContainerHeight = ShapeContainer.Height;
        }

        public virtual void OnImageLoad(Image image)
        {
            ImageLoaded?.Invoke(image);
        }


        protected override void OnControlAdded(ControlEventArgs e)
        {
            //e.Control.Size = Size;
            base.OnControlAdded(e);
        }

        private void OperationPanel_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
            {
                if (scalex < Math.Pow(2f, 16) && scaley < Math.Pow(2f, 16))
                {
                    scalex *= 2f;
                    scaley *= 2f;
                }
                else
                {
                    return;
                }
            }
            else
            {
                if (scalex > Math.Pow(0.5f,8) && scaley > Math.Pow(0.5f, 8))
                {
                    scalex *= 0.5f;
                    scaley *= 0.5f;
                }
                else
                {
                    return;
                }
            }
            int length = Controls.Count;
            for (int k = 0; k < length; k++)
            {
                UserControlX usercx = (UserControlX)Controls[k];
                float ofx = e.Location.X - (e.Location.X - usercx.OffsetX) / usercx.ScaleX;
                float ofy = e.Location.Y - (e.Location.Y - usercx.OffsetY) / usercx.ScaleY;
                usercx.ScaleX = scalex;
                usercx.ScaleY = scaley;
                usercx.OffsetX = ofx + (e.Location.X - ofx) * (1 - scalex);
                usercx.OffsetY = ofy + (e.Location.Y - ofy) * (1 - scaley);
            }
            ShapeContainer.Refresh();
        }

        private void 加载图片ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            DialogResult dialogResult = fileDialog.ShowDialog();
            if (dialogResult != DialogResult.OK) return;
            //Mat mat = CvInvoke.Imread(fileDialog.FileName, Emgu.CV.CvEnum.ImreadModes.AnyColor);
            //shapeContainer.ImageBases.Add(new ImageBase(Bitmap.FromFile(fileDialog.FileName))) ;
            ContempImage = Bitmap.FromFile(fileDialog.FileName);
            Dev_DispImage(ContempImage);
            OnImageLoad(ContempImage);
        }

        public void Dev_AutoFit()
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_AutoFit();
                }));
            }
            else
            {
                try
                {
                    if (ShapeContainer.ImageItems.Count == 0) return;
                    int w = ShapeContainer.ImageItems[0].Image.Width;
                    int h = ShapeContainer.ImageItems[0].Image.Height;
                    float sc1 = shapeContainerWidth * 1f / w;
                    float sc2 = shapeContainerHeight * 1f / h;
                    if (sc1 < sc2)
                    {
                        scalex = sc1;
                        scaley = sc1;
                    }
                    else
                    {
                        scalex = sc2;
                        scaley = sc2;
                    }
                    int length = Controls.Count;
                    for (int k = 0; k < length; k++)
                    {
                        UserControlX usercx = (UserControlX)Controls[length - k - 1];
                        usercx.ScaleX = scalex;
                        usercx.ScaleY = scaley;
                        float woff = (float)Math.Round((-w * 1f * scalex + shapeContainerWidth) / 2f, 3);
                        float hoff = (float)Math.Round((-h * 1f * scaley + shapeContainerHeight) / 2f, 3);
                        if (woff > 0)
                            usercx.OffsetX = woff;
                        else
                            usercx.OffsetX = 0f;
                        if (hoff > 0)
                            usercx.OffsetY = hoff;
                        else
                            usercx.OffsetY = 0f;
                        usercx.Refresh();
                    }
                }
                catch (Exception exp)
                {
                    //FastData.SaveStatic.SaveTxt("D:\\ERROR.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\tDev_AutoFit:" + exp.ToString(), true);
                }
            }
        }

        public void Dev_DispImage(Image bitmap)
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_DispImage(bitmap);
                }));
            }
            else
            {
                try
                {
                    ImageBase imageBase = new ImageBase(bitmap);
                    imageBase.PointFs = new PointF[2] { new PointF(0, 0), new PointF(Width, Height) };
                    ShapeContainer.ImageItems.Add(imageBase);
                    ShapeContainer.Refresh();
                }
                catch(Exception exp)
                {
                    //FastData.SaveStatic.SaveTxt("D:\\ERROR.txt",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")+ "\tDev_DispMat:" + exp.ToString(), true);
                }
            }
        }

        public void Dev_DispXld(ShapeBase xld)
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_DispXld(xld);
                }));
            }
            else
            {
                if (!ShapeContainer.ShapeItems.Contains(xld))
                {
                    ShapeContainer.ShapeItems.Add(xld);
                }
                xld.DrawColor = currentColor;
                xld.m_DrawColor = xld.DrawColor;
                xld.DrawLineWidth = currentWidth;
                ShapeContainer.Refresh();
            }
        }

        public void Dev_DispClearShapeItems()
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_DispClearShapeItems();
                }));
            }
            else
            {
                ShapeContainer.ShapeItems.Clear();
                Refresh();
            }
        }

        public void Dev_DispClearImageItems()
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_DispClearImageItems();
                }));
            }
            else
            {
                ShapeContainer.ImageItems.Clear();
                Refresh();
            }
        }


        public void Dev_DispClear()
        {
            if (ShapeContainer.InvokeRequired)
            {
                ShapeContainer.Invoke(new Action(() =>
                {
                    Dev_DispClear();
                }));
            }
            else
            {
                ShapeContainer.ShapeItems.Clear();
                ShapeContainer.ImageItems.Clear();
                Refresh();
            }
        }

        public void Dev_SetColor(Color color)
        {
            currentColor = color;
        }

        public void Dev_SetWidth(int width)
        {
            currentWidth = width;
        }

        public void Dev_GenCircleXld(float centerX, float centerY, float radius, out Circle circleXld)
        {
            circleXld = new Circle(centerX, centerY, radius);
        }

        public void Dev_GenRectancleXld(float centerX, float centerY, float width, float height, float angle, out Rectancle rectXld)
        {
            rectXld = new Rectancle(centerX, centerY, width, height, angle);
        }

        public void Dev_GenLineXld(PointF[] pointFs, out Line lineXld)
        {
            lineXld = new Line(pointFs);
        }

        public void Dev_GenCrossXld(PointF[] pointFs, float radius, float angle, out Cross crossXld)
        {

            crossXld = new Cross(pointFs, radius, angle);
        }

        //public void Dev_GenRectancleXld(PointF[] pointFs, out Rectancle rectancleXld)
        //{
          
        //}

        private void 自适应保持纵宽比ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Dev_AutoFit();
        }

        public void Fresh()
        {
            ShapeContainer.Refresh();
        }



        int anlgeDelt = 0;
        public void CoordinatePoint(PointF[] pointFs ,float minPix = 0.1f)
        {
            if (pointFs.Length != 0)
            {
                anlgeDelt += 45;
                Matrix matrix = new Matrix();
                matrix.Scale(1, -1);
                matrix.Translate(100, -300);
                matrix.TransformPoints(pointFs);
                Dev_SetWidth(1);
                Dev_SetColor(GetColor());
                Cross cross = new Cross(pointFs, 2, anlgeDelt);
                cross.MinPix = minPix;
                cross.MouseDown += Cross_MouseDown;
                Dev_DispXld(cross);
            }
        }

        public void CoordinateCross(Cross m_cross)
        {
            //Matrix matrix = new Matrix();
            //matrix.Scale(1, -1);
            //matrix.Translate(100, -300);
            //matrix.TransformPoints(m_cross.PointFs);
            Dev_DispXld(m_cross);
        }





        private void Cross_MouseDown(object sender, MouseEventArgs e)
        {
            ShapeSelected?.Invoke(this, (ShapeBase)sender);
        }

        private static Color[] Colors = new Color[] { Color.Red, Color.Green, Color.Blue, Color.Yellow, Color.Purple, Color.Pink };
        public void CoordinatePoint(List<PointF[]> pointFsList)
        {
            if (pointFsList.Count() != 0)
            {
                for (int i = 0; i < pointFsList.Count(); i++)
                {
                    CoordinatePoint(pointFsList[i]);
                }
            }
        }

        public void CoordinateMultiLine(List<PointF[]> pointFsList)
        {
            if (pointFsList.Count() != 0)
            {
                for (int i = 0; i < pointFsList.Count(); i++)
                {
                    if (pointFsList[i].Count() != 0)
                    {
                        anlgeDelt += 45;
                        Matrix matrix = new Matrix();
                        matrix.Scale(1, -1);
                        matrix.Translate(100, -300);
                        matrix.TransformPoints(pointFsList[i]);
                        Dev_SetWidth(3);
                        Dev_SetColor(Color.Blue);
                        Dev_DispXld(new Line(pointFsList[i]));
                    }
                }
            }
        }

        public void CoordinateMultiLine(PointF[] pointFsList)
        {
            List<PointF[]> pointFsLists = new List<PointF[]>();
            pointFsLists.Add(pointFsList);
            CoordinateMultiLine(pointFsLists);
        }

        int colorflag = 0;
        private Color GetColor()
        {
            Color color = Colors[colorflag];
            colorflag++;
            if (colorflag > Colors.Length - 1)
            {
                colorflag = 0;
            }
            return color;
        }
    }
}
